package blacknWhite.MarketSalesMonitor;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.MediaPlayer;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.ArrayAdapter;
import blacknWhite.Libraries.AppDatabase;
import blacknWhite.Libraries.CheckoutLibrary;
import blacknWhite.Libraries.MarketLibrary;
import blacknWhite.Libraries.Utils;
import blacknWhite.Libraries.AppDatabase.AppCommentsColumns;
import blacknWhite.Libraries.AppDatabase.OrdersColumns;

public class MonitorProcessor {
	public MonitorProcessor(Context ctx) {
		this.ctx = ctx;
	}

	public void onDestroy() {
		timerComments1.cancel();
		timerComments2.cancel();
		timerOders1.cancel();
		timerOders2.cancel();
	}

	private Context ctx;
	private static Timer timerOders1 = new Timer();
	private static Timer timerComments1 = new Timer();
	private static Timer timerOders2 = new Timer();
	private static Timer timerComments2 = new Timer();
	ArrayAdapter<View> adapterOrders;
	ArrayAdapter<View> adapterComments;

	private boolean IsServiceEnabled() {
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(ctx);

		boolean isEnabled = sp.getBoolean("serviceEnabled", true);
		return isEnabled;
	}

	private int getMillisecondsInterval() {
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(ctx);
		int millisecs = sp.getInt("frequencyEntries", 30);
		return millisecs * 60 * 1000;
	}

	void startservice() {
		try {
			long period = getMillisecondsInterval();
			TimerTask taskRefreshOrders = new TimerTask() {
				public void run() {
					RefreshOrders();
				}
			};
			timerOders1.scheduleAtFixedRate(taskRefreshOrders, 5000, period);

			TimerTask taskRefreshComments = new TimerTask() {
				public void run() {
					RefreshComments();
				}
			};
			timerComments1.scheduleAtFixedRate(taskRefreshComments, 10000,
					period);
		} catch (Exception e) {
			Utils.LogException(e);
		}
	}

	private void RefreshComments() {
		try {
			if (ctx == null)
				return;
			if (!IsServiceEnabled())
				((Service) ctx).stopSelf();
			else
				MarketLibrary.refreshComments(null, adapterComments, ctx);
		} catch (Exception e) {
			Utils.LogException(e);
		}
	}

	private void RefreshOrders() {
		try {
			if (ctx == null)
				return;
			if (!IsServiceEnabled())
				((Service) ctx).stopSelf();
			else
				CheckoutLibrary.refreshOrders(null, adapterOrders, ctx);
		} catch (Exception e) {
			Utils.LogException(e);
		}
	}

	void NotifyAndScheduleNextNewOrderNotification() {

		AppDatabase mOpenHelper = null;
		Cursor cursor = null;
		Editor spEditor = null;

		try {
			final SharedPreferences sp = PreferenceManager
					.getDefaultSharedPreferences(ctx);
			spEditor = sp.edit();

			long lastTimeOrderNotification = sp.getLong(
					"lastTimeOrderNotification", 0);

			mOpenHelper = new AppDatabase(ctx);
			final SQLiteDatabase db = mOpenHelper.getReadableDatabase();

			long saleDateLatestOrder = 0;
			// find date of latest order and use this one to start from
			cursor = db.query(AppDatabase.Tables.ORDERS, null, null, null,
					null, null, AppDatabase.OrdersColumns.SALE_DATE + " DESC");
			if (cursor.moveToFirst())
				saleDateLatestOrder = cursor
						.getLong(OrdersColumns.SALE_DATE_ID);
			else
				saleDateLatestOrder = lastTimeOrderNotification;
			cursor.close();

			if (saleDateLatestOrder == 0)
				return; // No orders found

			long saleDateLatestOrderMinusPeriod = saleDateLatestOrder
					- getMillisecondsInterval();

			if (lastTimeOrderNotification < saleDateLatestOrderMinusPeriod)
				lastTimeOrderNotification = saleDateLatestOrderMinusPeriod;

			if (saleDateLatestOrder == lastTimeOrderNotification)
				return; // notification for the latest order was already
			// anounced

			// Find the next sale date & time
			String query = AppDatabase.OrdersColumns.SALE_DATE + " > "
					+ lastTimeOrderNotification;
			cursor = db.query(AppDatabase.Tables.ORDERS, null, query, null,
					null, null, AppDatabase.OrdersColumns.SALE_DATE + " ASC");

			if (cursor.moveToFirst()) {
				// pull out order information
				lastTimeOrderNotification = cursor
						.getLong(OrdersColumns.SALE_DATE_ID);
				final Date lastTimeOrderNotificationDate = new Date(
						lastTimeOrderNotification);
				// Notify of new order
				final Runnable notifyUI = new Runnable() {
					public void run() {
						notifyNewOrder(sp, lastTimeOrderNotificationDate);
					}
				};
				Utils.handler.post(notifyUI);
			}

			// Find subsequent order and schedulr notification
			if (cursor.moveToNext()) {
				long nextNotification = cursor
						.getLong(OrdersColumns.SALE_DATE_ID);
				long differenceInMillisecs = nextNotification
						- lastTimeOrderNotification;

				TimerTask task = new TimerTask() {
					public void run() {
						NotifyAndScheduleNextNewOrderNotification();
					}
				};
				timerOders2.schedule(task, differenceInMillisecs);
			} else {
				timerOders2 = new Timer();
			}

			spEditor.putLong("lastTimeOrderNotification",
					lastTimeOrderNotification);
		} catch (Exception e) {
			Utils.LogException(e);
		} finally {
			if (cursor != null)
				cursor.close();
			if (spEditor != null)
				spEditor.commit();
		}
	}

	private void notifyNewOrder(final SharedPreferences sp,
			final Date lastTimeOrderNotificationDate) {
		try {
			java.text.DateFormat dateFormat = java.text.DateFormat
					.getTimeInstance();
			String dateOrder = dateFormat.format(lastTimeOrderNotificationDate);

			Utils.showToast(ctx, "New order @ " + dateOrder);
			boolean notificationNewOrder = sp.getBoolean(
					"notificationNewOrder", true);
			if (notificationNewOrder) {
				MediaPlayer mp = MediaPlayer.create(ctx, R.raw.cash_register);
				mp.start();
			}
		} catch (IllegalStateException e) {
			Utils.LogException(e);
		}
	}

	void NotifyAndScheduleNextNewCommentNotification() {

		AppDatabase mOpenHelper = null;
		Cursor cursor = null;
		Editor spEditor = null;

		try {
			final SharedPreferences sp = PreferenceManager
					.getDefaultSharedPreferences(ctx);
			spEditor = sp.edit();

			long lastTimeCommentNotification = sp.getLong(
					"lastTimeCommentNotification", 0);

			mOpenHelper = new AppDatabase(ctx);
			final SQLiteDatabase db = mOpenHelper.getReadableDatabase();

			long creationTimeLatestComment = 0;
			// find date of latest order and use this one to start from
			cursor = db.query(AppDatabase.Tables.APP_COMMENTS, null, null,
					null, null, null,
					AppDatabase.AppCommentsColumns.CREATION_TIME + " DESC");
			if (cursor.moveToFirst())
				creationTimeLatestComment = cursor
						.getLong(AppCommentsColumns.CREATION_TIME_ID);
			else
				creationTimeLatestComment = lastTimeCommentNotification;
			cursor.close();

			if (creationTimeLatestComment == 0)
				return; // No orders found

			long creationTimeLatestCommentMinusPeriod = creationTimeLatestComment
					- getMillisecondsInterval();

			if (lastTimeCommentNotification < creationTimeLatestCommentMinusPeriod)
				lastTimeCommentNotification = creationTimeLatestCommentMinusPeriod;

			if (creationTimeLatestComment == lastTimeCommentNotification)
				return; // notification for the latest order was already
			// anounced

			// Find the next sale date & time
			String query = AppDatabase.AppCommentsColumns.CREATION_TIME + " > "
					+ lastTimeCommentNotification;
			cursor = db.query(AppDatabase.Tables.APP_COMMENTS, null, query,
					null, null, null,
					AppDatabase.AppCommentsColumns.CREATION_TIME + " ASC");

			if (cursor.moveToFirst()) {
				// pull out comment information
				lastTimeCommentNotification = cursor
						.getLong(AppCommentsColumns.CREATION_TIME_ID);
				final Date lastTimeCommentNotificationDate = new Date(
						lastTimeCommentNotification);
				final float rating = (float) cursor
						.getFloat(AppCommentsColumns.RATING_ID);

				// Notify of new comment
				final Runnable notifyUI = new Runnable() {
					public void run() {
						notifyNewComment(sp, lastTimeCommentNotificationDate,
								rating);
					}
				};
				Utils.handler.post(notifyUI);
			}

			// Find subsequent comment and schedulr notification
			if (cursor.moveToNext()) {
				long nextNotification = cursor
						.getLong(AppCommentsColumns.CREATION_TIME_ID);
				long differenceInMillisecs = nextNotification
						- lastTimeCommentNotification;

				TimerTask task = new TimerTask() {
					public void run() {
						NotifyAndScheduleNextNewCommentNotification();
					}
				};
				timerComments2.schedule(task, differenceInMillisecs);
			} else {
				timerComments2 = new Timer();
			}

			spEditor.putLong("lastTimeCommentNotification",
					lastTimeCommentNotification);
		} catch (Throwable e) {
			Utils.LogException(e);
		} finally {
			if (cursor != null)
				cursor.close();
			if (spEditor != null)
				spEditor.commit();
		}
	}

	private void notifyNewComment(final SharedPreferences sp,
			final Date lastTimeCommentNotificationDate, final float rating) {
		try {
			java.text.DateFormat dateFormat = java.text.DateFormat
					.getTimeInstance();
			String dateComment = dateFormat
					.format(lastTimeCommentNotificationDate);

			Utils.showToast(ctx, "New comment @ " + dateComment);
			boolean notificationNewComment = sp.getBoolean(
					"notificationNewComment", true);
			if (notificationNewComment) {
				if (rating >= 4) {
					MediaPlayer mp = MediaPlayer.create(ctx, R.raw.cheer2);
					mp.start();
				} else if (rating <= 2) {
					MediaPlayer mp = MediaPlayer.create(ctx, R.raw.sfxboo);
					mp.start();
				} else // (rating is 3
				{
					MediaPlayer mp = MediaPlayer.create(ctx, R.raw.applause10);
					mp.start();
				}
			}
		} catch (IllegalStateException e) {
			Utils.LogException(e);
		}
	}
}
